home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / waisgate / HTFormat.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  11KB  |  437 lines

  1. /*        Manage different file formats            HTFormat.c
  2. **        =============================
  3. **
  4. ** Bugs:
  5. **    Not reentrant.
  6. **
  7. **    Assumes the incoming stream is ASCII, rather than a local file
  8. **    format, and so ALWAYS converts from ASCII on non-ASCII machines.
  9. **    Therefore, non-ASCII machines can't read local files.
  10. **
  11. */
  12.  
  13. /* Implements:
  14. */
  15. #include "HTFormat.h"
  16.  
  17. PUBLIC float HTMaxSecs = 1e10;        /* No effective limit */
  18. PUBLIC float HTMaxLength = 1e10;    /* No effective limit */
  19.  
  20. #ifdef unix
  21. #ifdef NeXT
  22. #define PRESENT_POSTSCRIPT "open %s; /bin/rm -f %s\n"
  23. #else
  24. #define PRESENT_POSTSCRIPT "(ghostview %s ; /bin/rm -f %s)&\n"    
  25.     /* Full pathname would be better! */
  26. #endif
  27. #endif
  28.  
  29.  
  30. #include "HTUtils.h"
  31. #include "tcp.h"
  32.  
  33. #include "HTML.h"
  34. #include "HTMLDTD.h"
  35. #include "HText.h"
  36. #include "HTAlert.h"
  37. #include "HTList.h"
  38. #include "HTInit.h"
  39. /*    Streams and structured streams which we use:
  40. */
  41. #include "HTFWriter.h"
  42. #include "HTPlain.h"
  43. #include "SGML.h"
  44. #include "HTML.h"
  45. #include "HTMLGen.h"
  46.  
  47. PUBLIC    BOOL HTOutputSource = NO;    /* Flag: shortcut parser to stdout */
  48. extern  BOOL interactive;
  49.  
  50. struct _HTStream {
  51.       CONST HTStreamClass*    isa;
  52.       /* ... */
  53. };
  54.  
  55.  
  56. /*    Presentation methods
  57. **    --------------------
  58. */
  59.  
  60. PUBLIC  HTList * HTPresentations = 0;
  61. PUBLIC  HTPresentation* default_presentation = 0;
  62.  
  63.  
  64. /*    Define a presentation system command for a content-type
  65. **    -------------------------------------------------------
  66. */
  67. PUBLIC void HTSetPresentation ARGS5(
  68.     CONST char *, representation,
  69.     CONST char *, command,
  70.     float,    quality,
  71.     float,    secs, 
  72.     float,    secs_per_byte
  73. ){
  74.  
  75.     HTPresentation * pres = (HTPresentation *)malloc(sizeof(HTPresentation));
  76.     if (pres == NULL) outofmem(__FILE__, "HTSetPresentation");
  77.     
  78.     pres->rep = HTAtom_for(representation);
  79.     pres->rep_out = WWW_PRESENT;        /* Fixed for now ... :-) */
  80.     pres->converter = HTSaveAndExecute;        /* Fixed for now ...     */
  81.     pres->quality = quality;
  82.     pres->secs = secs;
  83.     pres->secs_per_byte = secs_per_byte;
  84.     pres->rep = HTAtom_for(representation);
  85.     pres->command = 0;
  86.     StrAllocCopy(pres->command, command);
  87.     
  88.     if (!HTPresentations) HTPresentations = HTList_new();
  89.     
  90.     if (strcmp(representation, "*")==0) {
  91.         if (default_presentation) free(default_presentation);
  92.     default_presentation = pres;
  93.     } else {
  94.         HTList_addObject(HTPresentations, pres);
  95.     }
  96. }
  97.  
  98.  
  99. /*    Define a built-in Function for a content-type
  100. **    ---------------------------------------------
  101. */
  102. PUBLIC void HTSetConversion ARGS6(
  103.     CONST char *, representation_in,
  104.     CONST char *, representation_out,
  105.     HTConverter,    converter,
  106.     float,    quality,
  107.     float,    secs, 
  108.     float,    secs_per_byte
  109. ){
  110.  
  111.     HTPresentation * pres = (HTPresentation *)malloc(sizeof(HTPresentation));
  112.     if (pres == NULL) outofmem(__FILE__, "HTSetPresentation");
  113.     
  114.     pres->rep = HTAtom_for(representation_in);
  115.     pres->rep_out = HTAtom_for(representation_out);
  116.     pres->converter = converter;
  117.     pres->command = NULL;        /* Fixed */
  118.     pres->quality = quality;
  119.     pres->secs = secs;
  120.     pres->secs_per_byte = secs_per_byte;
  121.     pres->command = 0;
  122.     
  123.     if (!HTPresentations) HTPresentations = HTList_new();
  124.     
  125.     if (strcmp(representation_in, "*")==0) {
  126.         if (default_presentation) free(default_presentation);
  127.     default_presentation = pres;
  128.     } else {
  129.         HTList_addObject(HTPresentations, pres);
  130.     }
  131. }
  132.  
  133.  
  134.  
  135. /*    File buffering
  136. **    --------------
  137. **
  138. **    The input file is read using the macro which can read from
  139. **    a socket or a file.
  140. **    The input buffer size, if large will give greater efficiency and
  141. **    release the server faster, and if small will save space on PCs etc.
  142. */
  143. #define INPUT_BUFFER_SIZE 4096        /* Tradeoff */
  144. PRIVATE char input_buffer[INPUT_BUFFER_SIZE];
  145. PRIVATE char * input_pointer;
  146. PRIVATE char * input_limit;
  147. PRIVATE int input_file_number;
  148.  
  149.  
  150. /*    Set up the buffering
  151. **
  152. **    These routines are public because they are in fact needed by
  153. **    many parsers, and on PCs and Macs we should not duplicate
  154. **    the static buffer area.
  155. */
  156. PUBLIC void HTInitInput ARGS1 (int,file_number)
  157. {
  158.     input_file_number = file_number;
  159.     input_pointer = input_limit = input_buffer;
  160. }
  161.  
  162.  
  163. PUBLIC char HTGetChararcter NOARGS
  164. {
  165.     char ch;
  166.     do {
  167.     if (input_pointer >= input_limit) {
  168.         int status = NETREAD(
  169.             input_file_number, input_buffer, INPUT_BUFFER_SIZE);
  170.         if (status <= 0) {
  171.         if (status == 0) return (char)EOF;
  172.         if (TRACE) fprintf(stderr,
  173.             "HTFormat: File read error %d\n", status);
  174.         return (char)EOF; /* -1 is returned by UCX at end of HTTP link */
  175.         }
  176.         input_pointer = input_buffer;
  177.         input_limit = input_buffer + status;
  178.     }
  179.     ch = *input_pointer++;
  180.     } while (ch == (char) 13); /* Ignore ASCII carriage return */
  181.     
  182.     return FROMASCII(ch);
  183. }
  184.  
  185. /*    Stream the data to an ouput file as binary
  186. */
  187. PUBLIC int HTOutputBinary ARGS2( int,         input,
  188.                   FILE *,     output)
  189. {
  190.     do {
  191.         int status = NETREAD(
  192.             input, input_buffer, INPUT_BUFFER_SIZE);
  193.         if (status <= 0) {
  194.         if (status == 0) return 0;
  195.         if (TRACE) fprintf(stderr,
  196.             "HTFormat: File read error %d\n", status);
  197.         return 2;            /* Error */
  198.         }
  199.         fwrite(input_buffer, sizeof(char), status, output);
  200.     } while (YES);
  201. }
  202.  
  203.  
  204. /*        Create a filter stack
  205. **        ---------------------
  206. **
  207. **    If a widlcard match is made, a temporary HTPresentation
  208. **    structure is made to hold the destination format while the
  209. **    new stack is generated. This is just to pass the out format to
  210. **    MIME so far.  Storing the format of a stream in the stream might
  211. **    be a lot neater.
  212. */
  213. PUBLIC HTStream * HTStreamStack ARGS4(
  214.     HTFormat,        format_in,
  215.     HTFormat,        rep_out,
  216.     HTStream*,        sink,
  217.     HTParentAnchor*,    anchor)
  218. {
  219.     HTAtom * wildcard = HTAtom_for("*");
  220.     HTPresentation temp;
  221.     if (TRACE) fprintf(stderr,
  222.         "HTFormat: Constructing stream stack for %s to %s\n",
  223.     HTAtom_name(format_in),    
  224.     HTAtom_name(rep_out));
  225.         
  226.     if (rep_out == WWW_SOURCE ||
  227.         rep_out == format_in) return sink;
  228.  
  229.     if (!HTPresentations) HTFormatInit();    /* set up the list */
  230.     
  231.     {
  232.     int n = HTList_count(HTPresentations);
  233.     int i;
  234.     HTPresentation * pres;
  235.     for(i=0; i<n; i++) {
  236.         pres = HTList_objectAt(HTPresentations, i);
  237.         if (pres->rep == format_in) {
  238.             if (pres->rep_out == rep_out)
  239.                 return (*pres->converter)(pres, anchor, sink);
  240.         if (pres->rep_out == wildcard) {
  241.             temp = *pres;/* make temp conversion to needed fmt */
  242.             temp.rep_out = rep_out;        /* yuk */
  243.                 return (*pres->converter)(&temp, anchor, sink);
  244.         }
  245.         }
  246.     }
  247.     }
  248.     
  249. #ifdef XMOSAIC_HACK
  250.     return sink;
  251. #else
  252.     return NULL;
  253. #endif
  254. }
  255.     
  256.  
  257. /*        Find the cost of a filter stack
  258. **        -------------------------------
  259. **
  260. **    Must return the cost of the same stack which StreamStack would set up.
  261. **
  262. ** On entry,
  263. **    length    The size of the data to be converted
  264. */
  265. PUBLIC float HTStackValue ARGS4(
  266.     HTFormat,        format_in,
  267.     HTFormat,        rep_out,
  268.     float,            initial_value,
  269.     long int,        length)
  270. {
  271.     HTAtom * wildcard = HTAtom_for("*");
  272.  
  273.     if (TRACE) fprintf(stderr,
  274.         "HTFormat: Evaluating stream stack for %s worth %.3f to %s\n",
  275.     HTAtom_name(format_in),    initial_value,
  276.     HTAtom_name(rep_out));
  277.         
  278.     if (rep_out == WWW_SOURCE ||
  279.         rep_out == format_in) return 0.0;
  280.  
  281.     if (!HTPresentations) HTFormatInit();    /* set up the list */
  282.     
  283.     {
  284.     int n = HTList_count(HTPresentations);
  285.     int i;
  286.     HTPresentation * pres;
  287.     for(i=0; i<n; i++) {
  288.         pres = HTList_objectAt(HTPresentations, i);
  289.         if (pres->rep == format_in && (
  290.                 pres->rep_out == rep_out ||
  291.             pres->rep_out == wildcard)) {
  292.             float value = initial_value * pres->quality;
  293.         if (HTMaxSecs != 0.0)
  294.         value = value - (length*pres->secs_per_byte + pres->secs)
  295.                              /HTMaxSecs;
  296.         return value;
  297.         }
  298.     }
  299.     }
  300.     
  301.     return -1e30;        /* Really bad */
  302.  
  303. }
  304.     
  305.  
  306. /*    Push data from a socket down a stream
  307. **    -------------------------------------
  308. **
  309. **   This routine is responsible for creating and PRESENTING any
  310. **   graphic (or other) objects described by the file.
  311. **
  312. **   The file number given is assumed to be a TELNET stream ie containing
  313. **   CRLF at the end of lines which need to be stripped to LF for unix
  314. **   when the format is textual.
  315. **
  316. */
  317. PUBLIC void HTCopy ARGS2(
  318.     int,            file_number,
  319.     HTStream*,        sink)
  320. {
  321.     HTStreamClass targetClass;    
  322.     
  323. /*    Push the data, ignoring CRLF, down the stream
  324. **
  325. */
  326.     targetClass = *(sink->isa);    /* Copy pointers to procedures */
  327.     
  328.     /*    Push binary from socket down sink
  329.     */
  330.     for(;;) {
  331.     int status = NETREAD(
  332.         file_number, input_buffer, INPUT_BUFFER_SIZE);
  333.     if (status <= 0) {
  334.         if (status == 0) break;
  335.         if (TRACE) fprintf(stderr,
  336.         "HTFormat: Read error, read returns %d\n", status);
  337.         break;
  338.     }
  339.     (*targetClass.put_block)(sink, input_buffer, status);
  340.     } /* next bufferload */
  341.     
  342. }
  343.  
  344.  
  345. /*    Push data from a socket down a stream STRIPPING CR
  346. **    --------------------------------------------------
  347. **
  348. **   This routine is responsible for creating and PRESENTING any
  349. **   graphic (or other) objects described by the file.
  350. **
  351. **   The file number given is assumed to be a TELNET stream ie containing
  352. **   CRLF at the end of lines which need to be stripped to LF for unix
  353. **   when the format is textual.
  354. **
  355. */
  356. PUBLIC void HTCopyNoCR ARGS2(
  357.     int,            file_number,
  358.     HTStream*,        sink)
  359. {
  360.     HTStreamClass targetClass;    
  361.     
  362. /*    Push the data, ignoring CRLF, down the stream
  363. **
  364. */
  365.     targetClass = *(sink->isa);    /* Copy pointers to procedures */
  366.  
  367. /*    Push text from telnet socket down sink
  368. **
  369. **    @@@@@ To push strings could be faster? (especially is we
  370. **    cheat and don't ignore CR! :-}
  371. */  
  372.     HTInitInput(file_number);
  373.     for(;;) {
  374.     char character;
  375.     character = HTGetChararcter();
  376.     if (character == (char)EOF) break;
  377.     (*targetClass.put_character)(sink, character);           
  378.     }
  379. }
  380.  
  381.  
  382. /*    Parse a socket given format and file number
  383. **
  384. **   This routine is responsible for creating and PRESENTING any
  385. **   graphic (or other) objects described by the file.
  386. **
  387. **   The file number given is assumed to be a TELNET stream ie containing
  388. **   CRLF at the end of lines which need to be stripped to LF for unix
  389. **   when the format is textual.
  390. **
  391. */
  392. PUBLIC int HTParseSocket ARGS5(
  393.     HTFormat,        format_in,
  394.     HTFormat,        format_out,
  395.     HTParentAnchor *,    anchor,
  396.     int,            file_number,
  397.     HTStream*,        sink)
  398. {
  399.     HTStream * stream;
  400.     HTStreamClass targetClass;    
  401.  
  402.     stream = HTStreamStack(format_in,
  403.             format_out,
  404.              sink , anchor);
  405.     
  406.     if (!stream) {
  407.         char buffer[1024];    /* @@@@@@@@ */
  408.     sprintf(buffer, "Sorry, can't convert from %s to %s.",
  409.         HTAtom_name(format_in), HTAtom_name(format_out));
  410.     if (TRACE) fprintf(stderr, "HTFormat: %s\n", buffer);
  411.         return HTLoadError(sink, 501, buffer);
  412.     }
  413.     
  414. /*    Push the data, ignoring CRLF if necessary, down the stream
  415. **
  416. **
  417. **   @@  Bug:  This decision ought to be made based on "encoding"
  418. **   rather than on format.  @@@  Whne we handle encoding.
  419. **   The current method smells anyway.
  420. */
  421.     targetClass = *(stream->isa);    /* Copy pointers to procedures */
  422.     if (format_in == WWW_BINARY || HTOutputSource
  423.         || strstr(HTAtom_name(format_in), "image/")
  424.     || strstr(HTAtom_name(format_in), "video/")) { /* @@@@@@ */
  425.         HTCopy(file_number, stream);
  426.     } else {   /* ascii text with CRLFs :-( */
  427.         HTCopyNoCR(file_number, stream);
  428.     }
  429.     (*targetClass.end_document)(stream);
  430.     (*targetClass.free)(stream);
  431.     
  432.     return HT_LOADED;
  433. }
  434.  
  435.  
  436.  
  437.